package com.tiancheng.trade.payment.mq;

import com.tiancheng.trade.commom.core.data.MessageBody;
import com.tiancheng.trade.commom.core.data.notify.PayRefundSettleResultMsgBO;
import com.tiancheng.trade.commom.core.data.notify.PayResultMsgBO;
import com.tiancheng.trade.commom.core.data.notify.PaySettleResultMsgBO;
import com.tiancheng.trade.commom.core.enums.MessageTypeEnum;
import com.tiancheng.trade.commom.core.utils.IdWorkerUtils;
import com.tiancheng.trade.commom.core.utils.JsonUtil;
import com.tiancheng.trade.payment.bo.cmq.*;
import com.tiancheng.trade.payment.bo.meesage.PaymentCommonMessageBO;
import com.tiancheng.trade.payment.mq.producer.Payment2OrderMsgProducer;
import com.tiancheng.trade.payment.mq.producer.Payment2PaymentMsgProducer;
import com.tiancheng.trade.payment.mq.producer.PaymentSettle2OrderMsgProducer;
import com.tiancheng.trade.payment.util.JacksonJsonUtil;

import com.tiancheng.trade.payment.util.cmq.MessageSign;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;

/**
 * cmq消息推送
 *
 * @author kellen
 * @date 2024/3/26
 */
@Slf4j
@Component
public class PaymentCenterMsgProducer {

    @Resource
    private PaymentSettle2OrderMsgProducer paymentSettle2OrderMsgProducer;
    @Resource
    private Payment2OrderMsgProducer orderCenterProducer;
    @Resource
    private Payment2PaymentMsgProducer payment2PaymentMsgProducer;

    @Value(value = "${mq.signKey}")
    private String signKey;

    /**
     * 支付结果
     *
     * @param payResultMsgBO
     */
    public boolean payResult(PayResultMsgBO payResultMsgBO) {
        try {
            MessageBody msgBody = this.getMsgData(MessageTypeEnum.order_pay_result.getCode(), payResultMsgBO);
            String msgBodyStr = JsonUtil.toJsonString(msgBody);
            log.info("推送支付结果消息message:{}", msgBodyStr);
            sendCallbackMessage(msgBody, MessageTypeEnum.order_pay_result, 50);
            return true;
        } catch (Exception e) {
            log.error("cmq推送退款消息失败:{}, {}", JsonUtil.toJsonString(payResultMsgBO), e.getMessage(), e);
            return false;
        }
    }

    /**
     * 退款结果
     *
     * @param refundResultMsgBO
     */
    public boolean refundResult(RefundResultMsgBO refundResultMsgBO) {
        try {
            // 首先判断是否有特殊业务场景，需要指定回调，否则默认都回调到订单中心

            MessageBody msgBody = this.getMsgData(MessageTypeEnum.order_refund_result.getCode(), refundResultMsgBO);
            String msgBodyStr = JsonUtil.toJsonString(msgBody);
            log.info("推送退款消息message:{}", msgBodyStr);
            sendCallbackMessage(msgBody, MessageTypeEnum.order_refund_result, 50);
            log.info("推送退款结果消息完成");
            return true;
        } catch (Exception e) {
            log.error("cmq推送退款结果消息失败:{}, {}", JsonUtil.toJsonString(refundResultMsgBO), e.getMessage());
            return false;
        }
    }


    /**
     * 结算成功结果
     *
     * @param paySettleResultMsgBO
     */
    public boolean paySettleResult(PaySettleResultMsgBO paySettleResultMsgBO) {
        try {
            MessageBody msgBody = this.getMsgData(MessageTypeEnum.trade_payment_settle_result.getCode(), paySettleResultMsgBO);
            String msgBodyStr = JsonUtil.toJsonString(msgBody);
            log.info("推送支付结算结果消息message:{}", msgBodyStr);
            sendCallbackMessage(msgBody, MessageTypeEnum.trade_payment_settle_result, 5000);
            return true;
        } catch (Exception e) {
            log.error("cmq推送退款消息失败:{}, {}", JsonUtil.toJsonString(paySettleResultMsgBO), e.getMessage(), e);
            return false;
        }
    }

    /**
     * 结算成功结果
     *
     * @param refundSettleResultMsgBO
     */
    public boolean refundSettleResult(PayRefundSettleResultMsgBO refundSettleResultMsgBO) {
        try {
            MessageBody msgBody = this.getMsgData(MessageTypeEnum.trade_payment_refund_settle_result.getCode(), refundSettleResultMsgBO);
            String msgBodyStr = JsonUtil.toJsonString(msgBody);
            log.info("推送退款结算结果消息message:{}", msgBodyStr);
            sendCallbackMessage(msgBody, MessageTypeEnum.trade_payment_refund_settle_result, 5000);
            return true;
        } catch (Exception e) {
            log.error("推送退款结算消息失败:{}, {}", JsonUtil.toJsonString(refundSettleResultMsgBO), e.getMessage(), e);
            return false;
        }
    }


    /**
     * 推送给对账中心支付、退款流水数据
     *
     * @param tallyFlowMsgBO
     * @return
     */
    public boolean tallyFlow(TallyFlowMsgBO tallyFlowMsgBO) {
        try {
			/*MessageBody msgBody = this.getMsgData("settlement_tally_flow", tallyFlowMsgBO);
			String msgBodyStr = JsonUtil.toJsonString(msgBody);

			log.info("推送对账中心流水消息tag:{},message:{}", settlementMsgTag, msgBodyStr);

			TopicProducer producer = cmqProducer.getTopic(cmqTopic);
			String s=producer.publishMessage(msgBodyStr, Arrays.asList(settlementMsgTag));
			log.info("推送对账中心流水消息messageId:{}", s);*/
            return true;
        } catch (Exception e) {
            log.error("cmq推送对账中心流水失败:{}, {}", JsonUtil.toJsonString(tallyFlowMsgBO), e.getMessage());
            return false;
        }
    }


    /**
     * 二维码支付结果
     *
     * @param qrPayResultMsgBO
     */
    public boolean qrPayResult(QrPayResultMsgBO qrPayResultMsgBO) {
        try {
            // 首先判断是否有特殊业务场景，需要指定回调，否则默认都回调到订单中心
            MessageBody msgBody = this.getMsgData(MessageTypeEnum.qrc_pay.getCode(), qrPayResultMsgBO);
            String msgBodyStr = JsonUtil.toJsonString(msgBody);

            log.info("推送二维码支付结果消息:{}", msgBodyStr);
            //sendCallbackMessage(msgBody, PaymentRabBitMqEnums.QUEUE_PAYMENT_NOTIFY);
            return true;
        } catch (Exception e) {
            log.error("cmq推送二维码支付结果消息失败:{}, {}", JsonUtil.toJsonString(qrPayResultMsgBO), e.getMessage());
            return false;
        }
    }

    /**
     * 二维码支付结果
     *
     * @param qrTradeMsgBO
     */
    public boolean qrcTradeMsg(QrTradeMsgBO qrTradeMsgBO) {
        try {
            // 首先判断是否有特殊业务场景，需要指定回调，否则默认都回调到订单中心
            MessageBody msgBody = this.getMsgData(MessageTypeEnum.qrc_trade.getCode(), qrTradeMsgBO);
            String msgBodyStr = JsonUtil.toJsonString(msgBody);
            log.info("推送二维码交易消息:{}", msgBodyStr);
            //sendCallbackMessage(msgBody, PaymentRabBitMqEnums.QUEUE_PAYMENT_NOTIFY);
            return true;
        } catch (Exception e) {
            log.error("cmq推送二维码交易消息失败:{}, {}", JsonUtil.toJsonString(qrTradeMsgBO), e.getMessage());
            return false;
        }
    }

    /**
     * 二维码支付结果
     *
     * @param qrPayResultMsgBO
     */
    public boolean qrRefundResult(QrPayResultMsgBO qrPayResultMsgBO) {
        try {
            // 首先判断是否有特殊业务场景，需要指定回调，否则默认都回调到订单中心
            MessageBody msgBody = this.getMsgData(MessageTypeEnum.qrc_refund.getCode(), qrPayResultMsgBO);
            String msgBodyStr = JsonUtil.toJsonString(msgBody);
            log.info("推送二维码退款结果消息:{}", msgBodyStr);
            //sendCallbackMessage(msgBody, PaymentRabBitMqEnums.QUEUE_PAYMENT_NOTIFY);
            return true;
        } catch (Exception e) {
            log.error("cmq推送二维码退款结果消息失败:{}, {}", JsonUtil.toJsonString(qrPayResultMsgBO), e.getMessage());
            return false;
        }
    }


    /**
     * 发送支付中心支付状态、退款状态查询
     *
     * @param messageBO
     */
    public boolean setPaymentQueryMsg(PaymentCommonMessageBO messageBO) {
        MessageBody messageBody = new MessageBody();
        messageBody.setMessageId(IdWorkerUtils.getInstance().buildPartNumber());
        messageBody.setMessageType(messageBO.getMessageType().getCode());
        messageBody.setData(messageBO);
        messageBody.setNonce(UUID.randomUUID().toString().replace("-", ""));
        messageBody.setTimestamp(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")));
        Optional<String> sign = MessageSign.get(JsonUtil.fromJson(JsonUtil.toJsonString(messageBody), TreeMap.class), signKey);
        messageBody.setSign(sign.get());
        sendCallbackMessage(messageBody, messageBO.getMessageType(), Objects.isNull(messageBO.getRetryInterval()) ? 100 : messageBO.getRetryInterval());
        return true;
    }


    /**
     * 组织生成消息内容
     *
     * @param data
     * @return
     */
    private MessageBody getMsgData(String messageType, Object data) {
        MessageBody messageBody = new MessageBody();
        messageBody.setMessageId(IdWorkerUtils.getInstance().buildPartNumber());
        messageBody.setMessageType(messageType);
        messageBody.setData(data);
        messageBody.setNonce(UUID.randomUUID().toString().replace("-", ""));
        messageBody.setTimestamp(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")));

        Optional<String> sign = MessageSign.get(JsonUtil.fromJson(JsonUtil.toJsonString(messageBody), TreeMap.class), signKey);
        messageBody.setSign(sign.get());
        return messageBody;
    }

    /**
     * 发送回调消息
     *
     * @param msgBody
     */
    private void sendCallbackMessage(MessageBody msgBody, MessageTypeEnum messageTypeEnum, long expiration) {
        switch (messageTypeEnum) {
            case order_pay_result:
            case order_refund_result:
                // 推送订单支付消息到订单中心
                orderCenterProducer.sendMessage(msgBody, expiration);
                log.info("订单支付消息到订单中心完成");
                break;
            case trade_payment_settle_result:
            case trade_payment_refund_settle_result:
                paymentSettle2OrderMsgProducer.sendMessage(msgBody,expiration);
                break;
            case trade_payment_common_query_pay_result:
            case trade_payment_common_query_refund_result:
                // 支付中心支付状态查询、退款状态查询
                payment2PaymentMsgProducer.sendMessage(msgBody, expiration);
                break;
            case qrc_pay:
                break;
            case qrc_refund:
                break;
            case qrc_trade:
                break;
        }
    }
}
